package com.roads.project.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.roads.common.constant.Constants;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.StringUtils;
import com.roads.project.domain.ProBoq;
import com.roads.project.domain.ProInstitutionDetail;
import com.roads.project.mapper.ProBoqMapper;
import com.roads.project.mapper.ProInstitutionDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.roads.project.mapper.ProBoqMeterageMapper;
import com.roads.project.domain.ProBoqMeterage;
import com.roads.project.service.IProBoqMeterageService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 计量清单Service业务层处理
 *
 * @author nhp
 * @date 2021-12-14
 */
@Service
@Slf4j
public class ProBoqMeterageServiceImpl implements IProBoqMeterageService {

    @Autowired
    private ProBoqMeterageMapper mapper;

    @Autowired
    private ProBoqMapper boqMapper;

    @Autowired
    private ProInstitutionDetailMapper bidDetailMapper;

    /**
     * 根据主键ID查询详情
     *
     * @param id 计量清单主键
     * @return 计量清单
     */
    @Override
    public ProBoqMeterage getModelById(Long id) {
        return mapper.getModelById(id);
    }

    /**
     * 根据计量清单编号查询详情
     *
     * @param meterageBoqCode 计量清单编号
     * @return 计量清单
     */
    @Override
    public ProBoqMeterage getModelByCode(String meterageBoqCode) {
        return mapper.getModelByCode(meterageBoqCode);
    }

    /**
     * 查询列表
     *
     * @param model 计量清单
     * @return 计量清单
     */
    @Override
    public List<ProBoqMeterage> selectModelList(ProBoqMeterage model) {
        return mapper.selectModelList(model);
    }

    /**
     * 查询标段计量清单数量
     *
     * @param institutionCode 标段编号
     * @return 数量
     */
    @Override
    public int countMeterage(String institutionCode) {
        return mapper.countMeterage(institutionCode);
    }

    /**
     * 标段下的计量清单是否有参与计量
     *
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Override
    public boolean hasPartakeMeterage(String institutionCode) {
        int count = mapper.countPartakeMeterage(institutionCode);
        return count > 0;
    }

    /**
     * 变更令号下的变更计量清单是否参与计量
     *
     * @param changeOrderNo 变更令号
     * @return 结果
     */
    @Override
    public boolean hasPartakeMeterageByChangeOrderNo(String changeOrderNo) {
        int count = mapper.countPartakeMeterageByChangeOrderNo(changeOrderNo);
        return count > 0;
    }

    /**
     * 获取该计量清单合同计量数量
     *
     * @param meterageBoqCode 计量清单编号
     * @return 数量
     */
    @Override
    public int getContractMeterageCount(String meterageBoqCode) {
        return mapper.getContractMeterageCount(meterageBoqCode);
    }

    /**
     * 获取该计量清单变更计量数量
     *
     * @param meterageBoqCode 计量清单编号
     * @return 数量
     */
    @Override
    public int getChangeMeterageCount(String meterageBoqCode) {
        return mapper.getChangeMeterageCount(meterageBoqCode);
    }

    /**
     * 新增
     *
     * @param model 计量清单
     * @return 结果
     */
    @Override
    public int insert(ProBoqMeterage model) {
        model.setCreateTime(DateUtils.getNowDate());
        // 查询工程量清单
        ProBoq boq = boqMapper.getModelByInstitutionBoqCode(model.getInstitutionBoqCode());
        // 查询标段概况
        ProInstitutionDetail bidDetail = bidDetailMapper.getModelByInnerCode(boq.getInstitutionCode());
        Integer decimalPlace = bidDetail.getDecimalPlace2();
        // 设置字段
        model.setBoqCode(boq.getBoqCode());
        model.setBoqName(boq.getBoqName());
        model.setUnit(boq.getUnit());
        model.setPrice(boq.getPrice());
        BigDecimal amount = boq.getAmount();
        BigDecimal price = boq.getPrice();
        if (amount != null && price != null) {
            BigDecimal total = amount.multiply(price, new MathContext(decimalPlace, RoundingMode.HALF_UP));
            model.setTotal(total);
        }
        model.setAncestors(boq.getAncestors());
        model.setRemainderAmount(model.getAmount());
        int maxSerialNumber = mapper.getMaxSerialNumber(model.getInstitutionBoqCode());
        maxSerialNumber++;
        model.setSerialNumber(maxSerialNumber);
        model.setMeterageBoqCode(model.getInstitutionBoqCode() + Constants.BOQ_SEPARATOR + maxSerialNumber);
        return mapper.insert(model);
    }

    /**
     * 修改
     *
     * @param model 计量清单
     * @return 结果
     */
    @Override
    public int update(ProBoqMeterage model) {
        ProBoqMeterage old = mapper.getModelById(model.getMeterageBoqId());
        model.setUpdateTime(DateUtils.getNowDate());
        if (old.getAmount().compareTo(model.getAmount()) != 0) {
            model.setRemainderAmount(model.getAmount());
            model.setAlreadyAmount(BigDecimal.ZERO);
            model.setRemainderTotal(model.getTotal());
            model.setAlreadyTotal(BigDecimal.ZERO);
            model.setComplete(Constants.NO);
        }
        if (old.getTotal().compareTo(model.getTotal()) != 0) {
            model.setRemainderTotal(model.getTotal());
            model.setAlreadyTotal(BigDecimal.ZERO);
            model.setComplete(Constants.NO);
        }
        return mapper.update(model);
    }

    /**
     * 批量删除
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    public int deleteByIds(Long[] ids) {
        return mapper.deleteByIds(ids);
    }

    /**
     * 删除
     *
     * @param id 计量清单主键
     * @return 结果
     */
    @Override
    public int delete(Long id) {
        return mapper.delete(id);
    }

    /**
     * 根据变更令号删除变更计量清单
     *
     * @param changeOrderNo 变更令号
     * @return 结果
     */
    @Override
    public int deleteChangeBoqByChangeOrderNo(String changeOrderNo) {
        return mapper.deleteChangeBoqByChangeOrderNo(changeOrderNo);
    }

    /**
     * 清空标段计量清单
     *
     * @param institutionCode 标段编号
     */
    @Override
    public void clean(String institutionCode) {
        mapper.deleteByInstitutionCode(institutionCode);
    }

    /**
     * 生成计量清单
     *
     * @param userName 登录用户
     * @param detailBid 标段详情
     * @param institutionCode 标段编号
     * @param bigTypeValue 清单大类值
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int generate(String userName, ProInstitutionDetail detailBid, String institutionCode, String bigTypeValue) {
        // 分割大类
        String[] bigTypeArray = bigTypeValue.split(",");
        // 删除原有计量清单
        for (int i = 0; i < bigTypeArray.length; i++) {
            String bigType = bigTypeArray[i] + ",";
            mapper.deleteByBigType(institutionCode, bigType);
        }
        // 查询需要生成的工程量清单
        List<ProBoq> boqList = boqMapper.selectFindInSetList(institutionCode, bigTypeValue);
        // 生成计量清单
        List<ProBoqMeterage> insertList = new ArrayList<>();
        int serialNumber = 1;
        Date nowDate = DateUtils.getNowDate();
        for(ProBoq boq : boqList) {
            ProBoqMeterage boqMeterage = new ProBoqMeterage();
            boqMeterage.setMeterageBoqCode(boq.getInstitutionBoqCode() + Constants.BOQ_SEPARATOR + serialNumber);
            boqMeterage.setMeterageBoqType("0");
            boqMeterage.setInstitutionCode(institutionCode);
            boqMeterage.setInstitutionBoqCode(boq.getInstitutionBoqCode());
            boqMeterage.setBoqCode(boq.getBoqCode());
            boqMeterage.setBoqName(boq.getBoqName());
            boqMeterage.setAncestors(boq.getAncestors());
            boqMeterage.setUnit(boq.getUnit());
            BigDecimal amount = boq.getAmount();
            BigDecimal price = boq.getPrice();
            boqMeterage.setAmount(amount);
            boqMeterage.setRemainderAmount(amount);
            boqMeterage.setPrice(price);
            if (amount != null && price != null) {
                BigDecimal total = amount.multiply(price).setScale(detailBid.getDecimalPlace2(), BigDecimal.ROUND_HALF_UP);
                boqMeterage.setTotal(total);
                boqMeterage.setRemainderTotal(total);
            }
            boqMeterage.setOrderNum(BigDecimal.valueOf(boq.getOrderNum()));
            boqMeterage.setBeginStation(detailBid.getBeginStation());
            boqMeterage.setEndStation(detailBid.getEndStation());
            boqMeterage.setComplete(Constants.NO);
            boqMeterage.setSerialNumber(serialNumber);
            boqMeterage.setItem(boq.getItem());
            boqMeterage.setCreateBy(userName);
            boqMeterage.setCreateTime(nowDate);
            insertList.add(boqMeterage);
        }
        mapper.insertBatch(insertList);
        return 1;
    }

    /**
     * 计量清单导入
     *
     * @param list 数据集
     * @param institutionCode 标段编号
     * @param updateSupport 是否续导
     * @param userName 登录用户
     * @return 结果
     */
    @Override
    public String importData(List<ProBoqMeterage> list, String institutionCode, boolean updateSupport, String userName) {
        if (!StringUtils.isNotNull(list) || list.size() == 0) {
            return "导入数据不能为空！";
        }
        // 查询标段工程量清单所有叶子节点
        ProBoq search = new ProBoq();
        search.setInstitutionCode(institutionCode);
        List<ProBoq> boqList = boqMapper.selectLeafNodeAllList(search);
        // 获取标段详情
        ProInstitutionDetail bidDetail = bidDetailMapper.getModelByInnerCode(institutionCode);
        // 转map，方便获取
        Map<String, ProBoq> boqMap = new HashMap<>(boqList.size());
        for (ProBoq proBoq : boqList) {
            boqMap.put(proBoq.getBoqCode(), proBoq);
        }
        List<ProBoqMeterage> maxValueList = mapper.selectMaxSerialNumber(institutionCode);
        // 转map，方便获取
        Map<String, Integer> maxMap = new HashMap<>(maxValueList.size());
        for (ProBoqMeterage meterage : maxValueList) {
            if (updateSupport) {
                maxMap.put(meterage.getInstitutionBoqCode(), meterage.getSerialNumber());
            } else {
                maxMap.put(meterage.getInstitutionBoqCode(), 0);
            }
        }
        int failureNum = 0;
        int index = 2;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (ProBoqMeterage proBoqMeterage : list) {
            StringBuilder rowFailureMsg = new StringBuilder();
            try {
                String checkResult = validateData(proBoqMeterage, boqMap);
                if (!StringUtils.isEmpty(checkResult)) {
                    StringUtils.appendFailureMsg(rowFailureMsg, index, checkResult);
                    failureMsg.append(rowFailureMsg);
                    failureNum++;
                } else {
                    ProBoq proBoq = boqMap.get(proBoqMeterage.getBoqCode());
                    // 计量清单编码计算
                    String institutionBoqCode = proBoq.getInstitutionBoqCode();
                    Integer maxValue = maxMap.get(institutionBoqCode);
                    if (maxValue == null) {
                        maxValue = 1;
                    } else {
                        maxValue++;
                    }
                    maxMap.put(institutionBoqCode, maxValue);
                    String meterageBoqCode = institutionBoqCode + Constants.BOQ_SEPARATOR + maxValue;
                    proBoqMeterage.setMeterageBoqCode(meterageBoqCode);
                    proBoqMeterage.setInstitutionCode(institutionCode);
                    proBoqMeterage.setInstitutionBoqCode(institutionBoqCode);
                    proBoqMeterage.setUnit(proBoq.getUnit());
                    BigDecimal amount = proBoqMeterage.getAmount();
                    proBoqMeterage.setRemainderAmount(amount);
                    BigDecimal price = proBoq.getPrice();
                    proBoqMeterage.setPrice(price);
                    if (amount != null && price != null) {
                        BigDecimal total = amount.multiply(price).setScale(bidDetail.getDecimalPlace2(), BigDecimal.ROUND_HALF_UP);
                        proBoqMeterage.setTotal(total);
                        proBoqMeterage.setRemainderTotal(total);
                    }
                    proBoqMeterage.setAncestors(proBoq.getAncestors());
                    proBoqMeterage.setSerialNumber(maxValue);
                    proBoqMeterage.setOrderNum(BigDecimal.valueOf(proBoq.getOrderNum()));
                    proBoqMeterage.setMeterageBoqType("0");
                    proBoqMeterage.setComplete(Constants.NO);
                    proBoqMeterage.setCreateBy(userName);
                    proBoqMeterage.setCreateTime(DateUtils.getNowDate());
                }
                index++;
            } catch (Exception e) {
                failureNum++;
                rowFailureMsg.append(StringUtils.appendFailureMsg(rowFailureMsg, index, e.getMessage()));
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            return failureMsg.toString();
        } else {
            if (!updateSupport) {
                // 删除该标段下所有计量清单
                mapper.deleteByInstitutionCode(institutionCode);
            }
            // 批量插入计量清单
            mapper.insertBatch(list);
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + list.size() + " 条。");
        }
        return successMsg.toString();
    }

    private String validateData(ProBoqMeterage proBoqMeterage, Map<String, ProBoq> boqMap) {
        if (StringUtils.isEmpty(proBoqMeterage.getBoqCode())) {
            return "清单编号不能为空";
        }
        BigDecimal amount = proBoqMeterage.getAmount();
        if (!StringUtils.isDecimal(amount)) {
            return "数量不能为空";
        }
        ProBoq proBoq = boqMap.get(proBoqMeterage.getBoqCode());
        if (StringUtils.isNull(proBoq)) {
            return "标段工程量清单里未找到该清单编号";
        }
        return "";
    }

}
